/*
 * Licensed to the 南京汇海交通科技有限公司
 *
 * Copyright (c) 2025.
 * All rights reserved.
 *
 * 本软件属南京汇海交通科技有限公司所有，在未获得南京汇海交通科技有限公司正式授权情况下，任何企业和个人，不能获取、阅读、安装、传播本软件涉及的任何受知识产权保护的内容。
 */
package com.chframework.boot.web.exception.handler;

import cn.hutool.core.date.DatePattern;
import cn.hutool.core.util.IdUtil;
import com.chframework.boot.core.response.result.ApiResult;
import com.chframework.boot.core.support.ApiHelper;
import com.chframework.common.constant.ApplicationConstant;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.propertyeditors.CustomDateEditor;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.context.annotation.Bean;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.ControllerAdvice;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerAdapter;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.StringJoiner;

/**
 * 单体应用架构 - 全局异常处理类，捕获异常后 返回视图页面，使用ModelAndView返回类型
 */
@Slf4j
@ControllerAdvice
public class WebExceptionHandler {

    /**
     * 应用到所有使用了@RequestMapping注解的方法，在其执行之前初始化数据绑定器
     * 除了使用注解@ControllerAdvice可以配置全局的WebDataBinder，还可以使用RequestMappingHandlerAdapter
     */
    @Bean
    public RequestMappingHandlerAdapter webBindingInitializer() {
        RequestMappingHandlerAdapter adapter = new RequestMappingHandlerAdapter();
        adapter.setWebBindingInitializer(binder -> {
            // 把String类型的参数先trim再绑定
            binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
            // 把Date类型的参数先格式化再绑定
            binder.registerCustomEditor(Date.class, new CustomDateEditor(new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN), false));
        });
        return adapter;
    }

    /**
     * 把值绑定到Model中，使全局@RequestMapping可以获取到该值
     */
    @ModelAttribute
    public void addAttribute(Model model) {
        model.addAttribute(ApplicationConstant.RESPONSE_IDENTITY, IdUtil.objectId());
    }

    /*
     * 全局异常捕捉处理，返回视图(系统异常页面)
     *
    @ExceptionHandler(value = {WebException.class})
    public ModelAndView customViewExceptionHandler(WebException exception) {
        StringJoiner joiner = new StringJoiner("");
        ApiResult<Serializable> result = ApiHelper.buildResult(exception.getMessage(), joiner);
        log.error(joiner.toString(), exception);

        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("error"); // 返回的文件名
        modelAndView.addObject(result);

        return modelAndView;
    }*/

    /**
     * 全局异常捕捉处理，返回视图(系统异常页面)
     */
    @ExceptionHandler
    public ModelAndView customViewExceptionHandler(Exception exception) {
        StringJoiner joiner = new StringJoiner("");
        ApiResult<Object> result = ApiHelper.buildResult(exception.getMessage(), joiner);
        log.error(joiner.toString(), exception);

        ModelAndView modelAndView = new ModelAndView();
        modelAndView.setViewName("error"); // 返回的文件名
        modelAndView.addObject(result);

        return modelAndView;
    }

    /*
     * 全局异常捕捉处理，返回JSON格式类型（单体应用架构，前后端分离）
     * @ResponseBody
     * @ExceptionHandler(value = {WebException.class}) // 指定拦截异常的类型，由业务逻辑层(微服务)异常类统一处理异常信息
     * @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR) // 自定义浏览器返回状态码
     * public ApiResult<Serializable> jsonExceptionHandler(WebException exception) {
     *     log.error(exception.getErrMsg(), exception);
     *     return ApiResult.build()
     *             .setErrcode(exception.getErrCode())
     *             .setErrmsg(exception.getErrMsg())
     *             .setSuccess(false)
     *             .setData(null)
     *             .setRequestId(exception.getRequestId());
     * }
     */

}
